package main

import (
	"bufio"
	"fmt"
	"log"
	"os"
	"os/exec"
	"runtime"
	"strings"
	"time"
)

// 颜色定义
const (
	ColorRed    = "\033[31m"
	ColorGreen  = "\033[32m"
	ColorYellow = "\033[33m"
	ColorBlue   = "\033[34m"
	ColorReset  = "\033[0m"
)

// 打印带颜色的文本
func printColor(color, text string) {
	fmt.Printf("%s%s%s\n", color, text, ColorReset)
}

// 检查命令是否存在
func commandExists(cmd string) bool {
	_, err := exec.LookPath(cmd)
	return err == nil
}

// 执行命令并返回结果
func runCommand(cmd string, args ...string) error {
	command := exec.Command(cmd, args...)
	command.Stdout = os.Stdout
	command.Stderr = os.Stderr
	return command.Run()
}

// 执行命令并获取输出
func runCommandWithOutput(cmd string, args ...string) (string, error) {
	command := exec.Command(cmd, args...)
	output, err := command.Output()
	return string(output), err
}

// 等待用户输入
func waitForInput(prompt string) string {
	fmt.Print(prompt)
	reader := bufio.NewReader(os.Stdin)
	input, _ := reader.ReadString('\n')
	return strings.TrimSpace(input)
}

// 等待服务启动
func waitForService(serviceName string, checkFunc func() bool, maxAttempts int) bool {
	printColor(ColorBlue, fmt.Sprintf("检查%s服务状态...", serviceName))

	for i := 1; i <= maxAttempts; i++ {
		if checkFunc() {
			printColor(ColorGreen, fmt.Sprintf("%s服务运行正常", serviceName))
			return true
		}

		if i < maxAttempts {
			printColor(ColorYellow, fmt.Sprintf("%s服务可能还在启动中，请稍等... (%d/%d)", serviceName, i, maxAttempts))
			time.Sleep(2 * time.Second)
		}
	}

	printColor(ColorRed, fmt.Sprintf("%s服务启动失败", serviceName))
	return false
}

// 检查MySQL服务（本地）
func checkLocalMySQL() bool {
	// 这里假设本地MySQL通过默认端口3306提供服务，且有测试数据库连接的方式
	// 示例：使用mysqladmin命令检查
	_, err := runCommandWithOutput("mysqladmin", "ping", "-h", "localhost", "-P", "3306", "-u", "root", "-p", "password", "--silent")
	return err == nil
}

// 检查Redis服务（本地）
func checkLocalRedis() bool {
	// 假设本地Redis通过默认端口6379提供服务
	_, err := runCommandWithOutput("redis-cli", "ping")
	return err == nil
}

// 检查应用服务
func checkApp() bool {
	_, err := runCommandWithOutput("curl", "-s", "http://localhost:8080/api/v1/health")
	return err == nil
}

// 启动本地MySQL服务（这里需要根据实际本地MySQL的启动方式调整，比如Windows下可能是服务启动等）
func startLocalMySQL() error {
	printColor(ColorBlue, "启动本地MySQL服务...")
	// 示例：在Linux系统下通过systemctl启动MySQL服务
	if runtime.GOOS == "linux" {
		if err := runCommand("sudo", "systemctl", "start", "mysql"); err != nil {
			return err
		}
	} else if runtime.GOOS == "windows" {
		// Windows下启动MySQL服务的命令，需根据实际安装情况调整
		if err := runCommand("net", "start", "MySQL"); err != nil {
			return err
		}
	} else if runtime.GOOS == "darwin" {
		// macOS下启动MySQL服务的命令，需根据实际安装情况调整
		if err := runCommand("brew", "services", "start", "mysql"); err != nil {
			return err
		}
	}
	return nil
}

// 启动本地Redis服务（这里需要根据实际本地Redis的启动方式调整）
func startLocalRedis() error {
	printColor(ColorBlue, "启动本地Redis服务...")
	// 示例：直接启动redis-server
	if err := runCommand("redis-server"); err != nil {
		return err
	}
	return nil
}

// 启动本地数据库服务
func startLocalDatabaseServices() error {
	if err := startLocalMySQL(); err != nil {
		return err
	}
	if err := startLocalRedis(); err != nil {
		return err
	}
	return nil
}

// 启动本地完整环境（这里主要是启动本地数据库服务后，再启动应用）
func startLocalFullEnvironment() error {
	if err := startLocalDatabaseServices(); err != nil {
		return err
	}
	// 启动应用，假设应用启动命令为go run cmd/server/main.go
	printColor(ColorBlue, "启动应用服务...")
	return runCommand("go", "run", "cmd/server/main.go")
}

// 初始化数据库（本地）
func initLocalDatabase() error {
	printColor(ColorBlue, "初始化数据库结构...")

	if !commandExists("go") {
		printColor(ColorYellow, "Go环境未找到，跳过数据库初始化")
		return nil
	}

	// 设置环境变量，指向本地数据库
	os.Setenv("DATABASE_URL", "mysql://root:5define7eS@localhost:3306/sysu_giep?charset=utf8mb4&parseTime=True&loc=Local")

	printColor(ColorBlue, "运行数据库迁移...")

	// 运行数据库迁移命令，假设应用启动时会自动进行迁移
	cmd := exec.Command("go", "run", "cmd/server/main.go")
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr

	if err := cmd.Start(); err != nil {
		return err
	}

	// 等待应用启动
	time.Sleep(5 * time.Second)

	// 检查应用是否启动成功
	if waitForService("应用", checkApp, 10) {
		printColor(ColorGreen, "应用启动成功，数据库初始化完成")
	}

	// 停止应用进程
	cmd.Process.Kill()

	return nil
}

// 显示信息
func showInfo() {
	fmt.Println()
	printColor(ColorGreen, "========================================")
	printColor(ColorGreen, "        数据库构建完成！")
	printColor(ColorGreen, "========================================")
	fmt.Println()

	printColor(ColorBlue, "服务信息:")
	fmt.Println("MySQL:     localhost:3306")
	fmt.Println("Redis:     localhost:6379")
	fmt.Println("数据库名:   sysu_giep")
	fmt.Println("用户名:     root")
	fmt.Println("密码:       password")
	fmt.Println()

	printColor(ColorBlue, "管理命令:")
	// 本地服务的管理命令，需根据实际本地服务的管理方式调整
	fmt.Println("启动MySQL: 根据本地系统服务管理方式启动（如systemctl、net等）")
	fmt.Println("启动Redis: redis-server")
	fmt.Println("停止MySQL: 根据本地系统服务管理方式停止")
	fmt.Println("停止Redis: 找到redis-server进程并终止")
	fmt.Println("重启服务: 先停止再启动对应服务")
	fmt.Println()

	printColor(ColorBlue, "下一步:")
	fmt.Println("1. 运行应用: go run cmd/server/main.go")
	fmt.Println("2. 访问API: http://localhost:8080/api/v1/health")
	fmt.Println("3. 查看文档: http://localhost:8080/swagger/index.html")
	fmt.Println()

	// 询问是否启动应用
	startApp := waitForInput("是否现在启动应用? (y/N): ")
	if strings.ToLower(startApp) == "y" {
		printColor(ColorBlue, "启动应用服务...")
		runCommand("go", "run", "cmd/server/main.go")
	}
}

// 主函数
func main() {
	// 打印标题
	printColor(ColorBlue, "========================================")
	printColor(ColorBlue, "    中山大学研究生院校企对接平台")
	printColor(ColorBlue, "        本地数据库一键构建脚本")
	printColor(ColorBlue, "========================================")
	fmt.Println()

	// 检查本地MySQL和Redis相关命令是否存在
	if !commandExists("mysqladmin") {
		printColor(ColorRed, "错误: mysqladmin命令未找到，请确保本地MySQL已正确安装且可执行命令在PATH中")
		os.Exit(1)
	}
	if !commandExists("redis-cli") {
		printColor(ColorRed, "错误: redis-cli命令未找到，请确保本地Redis已正确安装且可执行命令在PATH中")
		os.Exit(1)
	}

	printColor(ColorGreen, "本地数据库相关命令检查通过")
	fmt.Println()

	// 选择操作
	printColor(ColorYellow, "请选择操作:")
	fmt.Println("1. 启动本地MySQL服务")
	fmt.Println("2. 启动本地Redis服务")
	fmt.Println("3. 启动本地数据库服务 (MySQL + Redis)")
	fmt.Println("4. 启动本地完整环境 (MySQL + Redis + 应用)")
	fmt.Println("5. 初始化本地数据库")
	fmt.Println()

	choice := waitForInput("请输入选择 (1-5): ")

	var err error
	switch choice {
	case "1":
		err = startLocalMySQL()
	case "2":
		err = startLocalRedis()
	case "3":
		err = startLocalDatabaseServices()
		if err == nil {
			waitForService("MySQL", checkLocalMySQL, 30)
			waitForService("Redis", checkLocalRedis, 10)
			showInfo()
		}
		return
	case "4":
		err = startLocalFullEnvironment()
		if err == nil {
			waitForService("MySQL", checkLocalMySQL, 30)
			waitForService("Redis", checkLocalRedis, 10)
			// 这里应用是直接启动的，可根据实际情况补充应用检查逻辑
			showInfo()
		}
		return
	case "5":
		err = initLocalDatabase()
		if err == nil {
			showInfo()
		}
		return
	default:
		printColor(ColorRed, "无效选择")
		os.Exit(1)
	}

	if err != nil {
		printColor(ColorRed, "操作失败")
		log.Fatal(err)
	}

	// 显示信息
	showInfo()
}
